<route lang="yaml">
meta:
enabled: false
</route>

<script setup lang="ts">
import type { School } from '@/api/modules/schools'
import type { FormInstance, FormRules } from 'element-plus'
import baiduApi from '@/api/modules/baiduTransApi'
import api from '@/api/modules/campusNews'
import schools from '@/api/modules/schools'
import uploadApi from '@/api/modules/uploadImages.ts'
// 引入 schools.ts 的 API
import useSettingsStore from '@/store/modules/settings'
import { QuillEditor } from '@vueup/vue-quill'
import { ElMessage } from 'element-plus'
import '@vueup/vue-quill/dist/vue-quill.snow.css'

// 学校名称列表
const schoolList = ref<School[]>([])
const searchKeyword = ref('')
const filteredSchools = ref<School[]>([])

const updateImg = ref(false)
const route = useRoute()
const router = useRouter()
const tabbar = useTabbar()
const settingsStore = useSettingsStore()
const loading = ref(false)
const translating = ref(false)
const formRef = useTemplateRef<FormInstance>('formRef')

// 富文本框
const quillEditorRef = ref<InstanceType<typeof QuillEditor>>()
const quillEditorEnRef = ref<InstanceType<typeof QuillEditor>>()

// 特殊字符检验
const validateNoSpecialChars = (value: string) => {
  // 允许字母、数字、汉字、空格、基本标点和中英文逗号，以及 - _ .
  return /[#$%&?]/.test(value) // 移除了 - _ .
}

interface FileInfo {
  file: File
  previewUrl: string
  name: string
  size: number
  type: string
}

const form = ref({
  newsId: route.params.id as string | number ?? '',
  newsTitle: '',
  newsTitleEn: '',
  schoolId: '',
  content: '',
  contentEn: '',
  newsUrls: [] as FileInfo[],
})

// 百度翻译接口
const translateText = async (text: string, from: string, to: string): Promise<string> => {
  try {
    const response = await baiduApi.translate({
      query: text,
      from,
      to,
    })
    console.log('翻译接口返回数据', response.data)
    return response.data.trans_result[0].dst
  }
  catch (error) {
    console.error('Translation failed:', error)
    ElMessage.error('翻译失败，请稍后再试')
    return ''
  }
}

const translateToEnglish = async (text: string) => {
  if (text && text.trim() !== '') {
    return translateText(text, 'zh', 'en')
  }
  return ''
}

// 标题翻译
const translateTitleToEnglish = async () => {
  form.value.newsTitleEn = await translateToEnglish(form.value.newsTitle)
}

// 内容翻译
const translateContentToEnglish = async () => {
  if (!form.value.content) {
    ElMessage.warning('请先输入中文内容')
    return
  }
  translating.value = true

  try {
    const parser = new DOMParser()
    const doc = parser.parseFromString(form.value.content, 'text/html')

    // 收集所有非 img 标签内的文本节点
    const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT, {
      acceptNode: (node) => {
        // 排除 img 标签内部的文本节点
        if (node.parentNode instanceof Element && node.parentNode.tagName.toLowerCase() === 'img') {
          return NodeFilter.FILTER_SKIP
        }

        // 确保获取到 img 标签之后的文本节点
        let currentNode = node.parentNode
        while (currentNode) {
          if (currentNode instanceof Element && currentNode.tagName.toLowerCase() === 'img') {
            return NodeFilter.FILTER_SKIP
          }
          currentNode = currentNode.parentNode
        }

        return NodeFilter.FILTER_ACCEPT
      },
    })

    const textNodes = []
    let node = walker.nextNode()
    while (node) {
      if (node.nodeValue?.trim()) {
        textNodes.push(node)
      }
      node = walker.nextNode()
    }

    // 逐个翻译文本节点（添加 1s 延迟）
    for (let i = 0; i < textNodes.length; i++) {
      const node = textNodes[i]
      const originalText = node.nodeValue!

      // 添加延迟，防止 QPS 超过限制
      await new Promise(resolve => setTimeout(resolve, 900))

      // 调用翻译接口
      node.nodeValue = await translateText(originalText, 'zh', 'en')
    }

    // 更新英文内容
    form.value.contentEn = doc.body.innerHTML
    ElMessage.success('翻译完成')

    // 更新英文富文本框的内容
    const enQuill = quillEditorEnRef.value?.getQuill()
    if (enQuill) {
      // 清空当前内容
      enQuill.setContents([])
      // 插入新的 HTML 内容
      enQuill.clipboard.dangerouslyPasteHTML(doc.body.innerHTML)
    }
  }
  catch (error) {
    console.error('翻译失败:', error)
    ElMessage.error('翻译失败，请稍后再试')
  }
  finally {
    translating.value = false
  }
}

const formRules = ref<FormRules>({
  newsTitle: [
    { required: true, message: '请输入新闻标题', trigger: 'blur' },
    { max: 200, message: '标题长度不能超过200个字符', trigger: 'blur' },
    {
      validator: (_, value, callback) => {
        if (validateNoSpecialChars(value)) {
          callback(new Error('不能包含特殊字符'))
        }
        else {
          callback()
        }
      },
      trigger: 'blur',
    },
  ],
  newsTitleEn: [
    { required: true, message: '请输入新闻英文标题', trigger: 'blur' },
    { max: 1000, message: '英文标题长度不能超过个1000字符', trigger: 'blur' },
    {
      validator: (_, value, callback) => {
        // 检查是否包含中文
        if (/[\u4E00-\u9FA5]/.test(value)) {
          callback(new Error('不能包含中文字符'))
          return
        }

        if (validateNoSpecialChars(value)) {
          callback(new Error('不能包含特殊字符'))
        }
        else {
          callback()
        }
      },
      trigger: 'blur',
    },
  ],
  content: [
    { required: true, message: '请输入新闻内容', trigger: 'blur' },
  ],
  contentEn: [
    { required: true, message: '请输入新闻英文内容', trigger: 'blur' },
  ],
  newsUrls: [
    {
      required: true,
      validator: (_, value, callback) => {
        if (!value || value.length === 0) {
          callback(new Error('请至少上传一张新闻图片'))
        }
        else {
          callback()
        }
      },
      trigger: 'blur',
    },
  ],
})

// 更新schoolList的学校名称
async function fetchSchoolList() {
  try {
    const res = await schools.SchoolNamelist({})
    console.log('获取学校列表成功:', res.data)
    schoolList.value = res.data || []
  }
  catch (error) {
    ElMessage.error('获取学校列表失败')
    console.error('获取学校列表失败:', error)
  }
}
// 模糊查询
function remoteSearchSchools(query: string) {
  searchKeyword.value = query
  if (query !== '') {
    filteredSchools.value = schoolList.value.filter(school =>
      school.schoolName.toLowerCase().includes(query.toLowerCase()),
    )
  }
  else {
    filteredSchools.value = schoolList.value
  }
}

// 实时监听下拉框输入
watch(searchKeyword, (newQuery) => {
  remoteSearchSchools(newQuery)
})

onMounted(async () => {
  await fetchSchoolList() // 先加载 schoolList 数据
  if (form.value.newsId !== '') {
    getInfo()
  }
})

function getInfo() {
  loading.value = true
  const themeId = form.value?.newsId
  if (themeId) {
    const idNumber = Number(themeId)
    api.detail(idNumber).then((res: any) => {
      loading.value = false
      const data = res.data.data

      // 将后端返回的字符串URL转换为数组
      const urlArray = data.newsUrl ? data.newsUrl.split(',') : []

      form.value.newsId = data.newsId
      form.value.newsTitle = data.newsTitle
      form.value.newsTitleEn = data.newsTitleEn
      form.value.schoolId = data.schoolId
      form.value.content = data.content
      form.value.contentEn = data.contentEn
      form.value.newsUrls = urlArray.map((url: string) => ({
        previewUrl: url,
        name: url.split('/').pop() || '',
        size: 0,
        type: 'image/jpeg',
        file: new File([], ''), // 编辑模式下不需要实际的文件对象
      }))

      remoteSearchSchools('')
    })
  }
}

// 富文本图片插入时只做本地预览（base64），不立即上传
function onQuillImageAdded(file: File, insertImage: (_url: string) => void) {
  const reader = new FileReader()
  reader.onload = (e) => {
    insertImage(e.target?.result as string)
  }
  reader.readAsDataURL(file)
}

// base64转File工具
function dataURLtoFile(dataurl: string, filename: string) {
  const arr = dataurl.split(',')
  const mime = arr[0].match(/:(.*?);/)![1]
  const bstr = atob(arr[1])
  let n = bstr.length
  const u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], filename, { type: mime })
}

async function onSubmit() {
  try {
    loading.value = true
    await formRef.value?.validate()

    // 1. 找到所有 base64 图片
    const contentHtml = form.value.content
    const imgReg = /<img[^>]+src="(data:image\/[^"]+)"[^>]*>/g
    let match: RegExpExecArray | null
    const base64List: string[] = []
    match = imgReg.exec(contentHtml)
    while (match !== null) {
      base64List.push(match[1])
      match = imgReg.exec(contentHtml)
    }

    // 2. 批量上传所有 base64 图片
    let newContent = contentHtml
    for (const base64 of base64List) {
      // base64 转 File
      const file = dataURLtoFile(base64, 'image.png')
      const formData = new FormData()
      formData.append('files', file)
      const uploadRes = await uploadApi.uploadImages(formData)
      const url = Array.isArray(uploadRes.data) ? uploadRes.data[0] : uploadRes.data
      // 替换内容中的 base64 为真实url
      newContent = newContent.replace(base64, url)
    }

    // 3. newsUrl 字段处理（保持原有逻辑）
    const newFiles = form.value.newsUrls.filter(item => item.file.size > 0)
    let uploadedUrls: string[] = []
    if (newFiles.length > 0) {
      const formData = new FormData()
      newFiles.forEach((fileInfo) => {
        formData.append('files', fileInfo.file)
      })
      const uploadRes = await uploadApi.uploadImages(formData)
      uploadedUrls = uploadRes.data
    }
    const existingUrls = form.value.newsUrls
      .filter(item => !item.file.size && item.previewUrl)
      .map(item => item.previewUrl)
    const allUrls = [...existingUrls, ...uploadedUrls].join(',')

    // 4. 提交替换后的内容
    const newsData = {
      newsId: Number(form.value.newsId) || 0,
      newsTitle: form.value.newsTitle,
      newsTitleEn: form.value.newsTitleEn,
      schoolId: Number(form.value.schoolId),
      content: newContent,
      contentEn: form.value.contentEn,
      newsUrl: allUrls,
    }
    // ...后续提交逻辑
    if (form.value.newsId === '') {
      await api.create(newsData)
      ElMessage.success('新增成功')
    }
    else {
      await api.edit(newsData)
      ElMessage.success('编辑成功')
    }
    goBack()
  }
  catch (error) {
    console.error('提交失败:', error)
    ElMessage.error('提交失败，请稍后再试')
  }
  finally {
    loading.value = false
  }
}

function onCancel() {
  goBack()
}
// 返回列表页
function goBack() {
  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
    tabbar.close({ name: 'schoolNews' })
  }
  else {
    router.push({ name: 'schoolNews' })
  }
}

// 上传文件
async function handlePhotoSuccess(options: { file: File }) {
  updateImg.value = true
  try {
    const previewUrl = URL.createObjectURL(options.file)
    form.value.newsUrls = [...form.value.newsUrls, {
      file: options.file,
      previewUrl,
      name: options.file.name,
      size: options.file.size,
      type: options.file.type,
    }]
    ElMessage.success('添加成功')
  }
  catch (error) {
    console.log('添加失败', error)
    ElMessage.error('添加失败')
  }
  finally {
    updateImg.value = false
  }
}

// 清理预览URL
onBeforeUnmount(() => {
  form.value.newsUrls.forEach((item) => {
    if (item.previewUrl && item.previewUrl.startsWith('blob:')) {
      URL.revokeObjectURL(item.previewUrl)
    }
  })
})

// 富文本框新增图片插入函数
const insertImage = async () => {
  const input = document.createElement('input')
  input.setAttribute('type', 'file')
  input.setAttribute('accept', 'image/*')
  input.click()

  input.onchange = async () => {
    const file = input.files?.[0]
    if (file) {
      const reader = new FileReader()
      reader.onload = async (e) => {
        const base64Url = e.target?.result as string

        // 使用 pasteHTML 插入带样式的 img 标签
        const html = `<img src="${base64Url}" style="max-height:100px; width:auto;" alt="">`

        // 插入到中文富文本框
        const quill = quillEditorRef.value?.getQuill()
        const length = quill?.getLength() || 0
        quill?.clipboard.dangerouslyPasteHTML(length, html)
        quill?.insertText(length + 1, '\n', 'user')

        // 插入到英文富文本框
        const enQuill = quillEditorEnRef.value?.getQuill()
        const enLength = enQuill?.getLength() || 0
        enQuill?.clipboard.dangerouslyPasteHTML(enLength, html)
        enQuill?.insertText(enLength + 1, '\n', 'user')
      }
      reader.readAsDataURL(file)
    }
  }
}
</script>

<template>
  <div class="absolute size-full flex flex-col">
    <FaPageHeader :title="route.name === 'newsCreate' ? '新增新闻' : '编辑新闻'" class="mb-0">
      <ElButton size="default" round @click="goBack">
        <template #icon>
          <FaIcon name="i-ep:arrow-left" />
        </template>
        返回
      </ElButton>
    </FaPageHeader>
    <ElForm ref="formRef" :model="form" :rules="formRules" label-width="130px" label-suffix="：" class="custom-form">
      <FaLayoutContainer right-side-width="500px" hide-right-side-toggle class="static" right-side-class="flex flex-col">
        <ElFormItem label="新闻标题" prop="newsTitle">
          <ElInput
            v-model="form.newsTitle"
            placeholder="请输入新闻标题"
            maxlength="200"
            show-word-limit
          >
            <template #append>
              <ElButton @click="translateTitleToEnglish">
                翻译
              </ElButton>
            </template>
          </ElInput>
        </ElFormItem>
        <ElFormItem label="新闻英文标题" prop="newsTitleEn">
          <ElInput
            v-model="form.newsTitleEn"
            placeholder="请输入新闻英文标题"
            maxlength="1000"
            show-word-limit
          />
        </ElFormItem>
        <ElFormItem label="新闻内容" prop="content">
          <div class="quill-editor-wrapper">
            <QuillEditor
              ref="quillEditorRef"
              v-model:content="form.content"
              content-type="html"
              placeholder="请输入新闻内容"
              style="min-height: 200px;"
              @image-added="onQuillImageAdded"
            />
            <ElButton
              style="margin-top: 8px;"
              :loading="translating"
              @click="translateContentToEnglish"
            >
              翻译
            </ElButton>
            <ElButton
              style="margin-top: 8px; margin-left: 8px;"
              @click="insertImage"
            >
              插入图片
            </ElButton>
          </div>
        </ElFormItem>
        <ElFormItem label="新闻英文内容" prop="contentEn">
          <div class="quill-editor-wrapper">
            <QuillEditor
              ref="quillEditorEnRef"
              v-model:content="form.contentEn"
              content-type="html"
              placeholder="请输入新闻英文内容"
              style="min-height: 200px;"
            />
          </div>
        </ElFormItem>

        <ElFormItem label="新闻图片" prop="newsUrls">
          <ImagesUpload
            v-model="form.newsUrls"
            :limit="9"
            :size="10"
            multiple
            action=""
            :loading="updateImg"
            name="newsUrls"
            :width="150"
            :height="150"
            :http-request="handlePhotoSuccess"
          />
          <!-- 编辑模式使用预览组件 -->
          <!--          <div v-else class="image-preview-container"> -->
          <!--            <ImagePreview -->
          <!--              v-for="(news, index) in form.newsUrls" -->
          <!--              :key="index" -->
          <!--              :src="news.previewUrl" -->
          <!--              class="preview-image" -->
          <!--              alt="新闻图片" -->
          <!--              :width="150" -->
          <!--              :height="150" -->
          <!--            /> -->
          <!--          </div> -->
        </ElFormItem>
      </FaLayoutContainer>
    </ElForm>
    <FaFixedActionBar>
      <ElButton type="primary" size="large" @click="onSubmit">
        提交
      </ElButton>
      <ElButton size="large" @click="onCancel">
        取消
      </ElButton>
    </FaFixedActionBar>
  </div>
</template>

<style scoped>
.custom-form {
  display: flex;
  flex: 1;
  overflow: auto;
}

.quill-editor-wrapper {
  width: 100%;
  margin: 0; /* 避免多余间距 */
}

.quill-editor-wrapper >>> img {
  width: auto !important;
  max-height: 100px !important;
}
</style>
